package com.weipu.common.okhttp;

import com.google.gson.Gson;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.internal.framed.Header;
import com.weipu.common.constants.Constant;
import com.weipu.common.constants.DxConfig;
import com.weipu.common.constants.ServerConstant;
import com.weipu.common.facade.exception.DxException;
import com.weipu.common.util.Common;
import com.weipu.common.util.JsonFormat;
import com.weipu.common.util.Logger;
import com.weipu.common.facade.model.Parmars;
import com.weipu.common.util.Logger;
import com.weipu.common.util.SecurityUtil;
import java.io.IOException;
import java.net.CookieManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

/**
 * okHttp帮助类 获取OKHttpClient网络请求对象 以及实现网络请求方法
 *
 * @author huangfei
 */
public class OkHttpHelper {
    private static final int TIMEOUT = 60000;
    private static OkHttpHelper okHttpHelper;

    private OkHttpClient okHttpClient;

    // 网络请求媒体类型
    MediaType mediaType = MediaType.parse("application/json; charset=utf-8");

    // 鉴权帐号及密码
    // String credential =
    // Credentials.basic(ServerConstant.Parameter.PARAMETER_DEV_AUTHENTICATE_ACCOUNT,
    // ServerConstant.Parameter.PARAMETER_DEV_AUTHENTICATE_PASSWORD);
    private OkHttpHelper() {

    }

	/**
	 * 获取权限帐号
	 *
	 * @return
	 */
	public String getCredential() {
		String credential;
		try {
			credential = Credentials
					.basic(SecurityUtil
							.aesEncrypt(ServerConstant.Parameter.PARAMETER_DEV_AUTHENTICATE_ACCOUNT),
							SecurityUtil
									.aesEncrypt(ServerConstant.Parameter.PARAMETER_DEV_AUTHENTICATE_PASSWORD));
		} catch (Exception e) {
			credential = Credentials
					.basic(ServerConstant.Parameter.PARAMETER_DEV_AUTHENTICATE_ACCOUNT,
							ServerConstant.Parameter.PARAMETER_DEV_AUTHENTICATE_PASSWORD);
		}
		return credential;
	}

    public String getCredentialNoJiaMi() {
        String credential;
        // try {
        // credential =
        // Credentials.basic(SecurityUtil.aesEncrypt(ServerConstant.Parameter.PARAMETER_DEV_AUTHENTICATE_ACCOUNT),
        // SecurityUtil.aesEncrypt(ServerConstant.Parameter.PARAMETER_DEV_AUTHENTICATE_PASSWORD));
        // } catch (Exception e) {
        credential = Credentials.basic(
                ServerConstant.Parameter.PARAMETER_DEV_AUTHENTICATE_ACCOUNT,
                ServerConstant.Parameter.PARAMETER_DEV_AUTHENTICATE_PASSWORD);
        // }
        return credential;
    }

    /**
     * 获取OkHttpHelper单例
     */
    public static OkHttpHelper getOkHttpHelperInstance() {
        if (null == okHttpHelper) {
            okHttpHelper = new OkHttpHelper();
        }
        return okHttpHelper;
    }

    /**
     * 获取OkHttpClient对象
     *
     * @return
     */
    public OkHttpClient getOkHttpClient() {
        if (null == okHttpClient) {
            okHttpClient = new OkHttpClient();

            if (DxConfig.HTTPS_VERIFY) {
                // 添加对https TLS1.2的支持
                SSLSocketFactoryEx factory = null;
                try {
//				 factory=new SSLSocketFactoryEx(null,null,null);
                    //TODO 该作用是结合X509功能 信任全部证书 用作离线环境测试 正式环境需要屏蔽
                    factory = new SSLSocketFactoryEx();
//				factory=new SSLSocketFactoryEx();
                } catch (KeyManagementException e) {
                } catch (NoSuchAlgorithmException e) {
                }
                if (null != factory) {
                    okHttpClient.setSslSocketFactory(factory);
                }
                // 信任证书设置 TODO 该作用是结合X509功能 信任全部证书 用作离线环境测试 正式环境需要屏蔽
                okHttpClient.setHostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                });
            }
            // 网络超时时间
            okHttpClient.setConnectTimeout(TIMEOUT, TimeUnit.MILLISECONDS);
            okHttpClient.setReadTimeout(TIMEOUT, TimeUnit.MILLISECONDS);
        }
        return okHttpClient;
    }

    /**
     * 同步的Post请求
     *
     * @param url          请求地址
     * @param parmars      请求参数
     * @param currencyCode 货币种类
     * @return
     * @throws IOException
     * @throws DxException
     */
    public String syncPostRequest(String url, Object parmars,
                                  String currencyCode) throws IOException, DxException {
        RequestBody body = RequestBody.create(mediaType,
                JsonUtils.getJsonStringByBean(parmars));
        Request.Builder builder = getDefaultRequestBuild(currencyCode, url);
        Request request = builder.post(body).build();
        Response response = getOkHttpClient().newCall(request).execute();
        if (response.isSuccessful()) {
            String result = response.body().string();
//            Logger.d("Result", result);
            Logger.e("Result",JsonFormat.format(result));
            return result;
        } else {
//            Logger.d("Result", response.toString());
            Logger.e("Result", JsonFormat.format(response.toString()));

            throw new DxException(response.code() + "");
        }
    }


    /**
     * 同步的Get请求
     *
     * @param url          请求地址
     * @param currencyCode 货币符号
     * @return
     * @throws IOException
     * @throws DxException
     */
    public String syncGetRequestByParams(String url, Parmars parmars)
            throws IOException, DxException {
        url = url + "?CustomerID=" + parmars.getCustomerID() + "&Token=" + parmars.getToken();
        Request.Builder builder = getDefaultRequestBuild("", url);
        Request request = builder.build();
        Response response = getOkHttpClient().newCall(request).execute();
        if (response.isSuccessful()) {
            String result = response.body().string();
            Logger.i("Result", result);
            return result;
        } else {
            Logger.i("Result", response.toString() + "   ");
            throw new DxException(response.code() + "");
        }
    }

    /**
     * 异步的Post请求
     *
     * @param url          请求Url
     * @param parmars      Bean请求参数
     * @param currencyCode 请求货币
     * @param callBack     回调CallBack
     */
    public void asyncPostRequest(String url, Object parmars,
                                 String currencyCode, DxOkHttpCallback callBack) {
        // TODO 实现异步的Post请求
        RequestBody body = RequestBody.create(mediaType,
                JsonUtils.getJsonStringByBean(parmars));
//		Request.Builder builder = new Request.Builder();
//		builder.headers(getRequestHeaders(currencyCode));
//		Request request = builder.url(url).post(body).build();
        Request.Builder builder = getDefaultRequestBuild(currencyCode, url);
        Request request = builder.post(body).build();
        getOkHttpClient().newCall(request).enqueue(callBack);
    }


    /**
     * 同步的Delete请求
     *
     * @param url          请求地址
     * @param parmars      请求参数
     * @param currencyCode 货币种类
     * @return
     * @throws IOException
     * @throws DxException
     */
    public String syncDeleteRequest(String url, Object parmars,
                                    String currencyCode) throws IOException, DxException {
        RequestBody body = RequestBody.create(mediaType,
                JsonUtils.getJsonStringByBean(parmars));
        Request.Builder builder = getDefaultRequestBuild(currencyCode, url);
        Request request = builder.delete(body).build();
        Response response = getOkHttpClient().newCall(request).execute();
        if (response.isSuccessful()) {
            String result = response.body().string();
            Logger.i("Result", result);
            return result;
        } else {
            Logger.d("Result", response.toString());
            throw new DxException(response.code() + "");
        }
    }

    /**
     * 同步的Get请求
     *
     * @param url          请求地址
     * @param currencyCode 货币符号
     * @return
     * @throws IOException
     * @throws DxException
     */
    public String syncGetRequest(String url, String currencyCode)
            throws IOException, DxException {
        Request.Builder builder = getDefaultRequestBuild(currencyCode, url);
        Request request = builder.build();
        Response response = getOkHttpClient().newCall(request).execute();
        if (response.isSuccessful()) {
            String result = response.body().string();
//            Logger.i("Result", result);
            Logger.e("Result", JsonFormat.format(result));

            return result;
        } else {
            Logger.i("Result", response.toString() + "   ");
            throw new DxException(response.code() + "");
        }
    }

	/**
	 * 同步的get请求 通过请求头
	 * @param url
	 * @return
	 * @throws IOException
     * @throws DxException
     */
	public String syncGetRequestByHeader(String url, String currencyCode,String headName,String headValue)
			throws IOException, DxException {
		Request.Builder builder=getDefaultRequestBuild(currencyCode,url);
		//添加请求头
		builder.addHeader(headName, headValue);
		Request request = builder.build();
		Response response = getOkHttpClient().newCall(request).execute();
		if (response.isSuccessful()) {
			String result = response.body().string();

			Logger.i("Result", result);
			return result;
		} else {
			Logger.i("Result", response.toString() + "   ");
			throw new DxException(response.code() + "");
		}
	}


    /**
     * 同步get请求，通过传入一个Model类来直接返回数据类型
     * @param url 请求地址
     * @param cls Model类
     * @param <T> 泛型
     * @return
     */
    public <T> T syncGetRequestByModel(String url, final Class<T> cls) {
        OkHttpClient okHttpClient = getOkHttpClient();
        Request request = getDefaultRequestBuild("", url).get().build();
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            String result = response.body().string();
            Gson gson = new Gson();
            T updateModel = (T) gson.fromJson(result, cls);
            return updateModel;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 异步的Get请求
     *
     * @param url          请求地址
     * @param currencyCode 货币符号
     * @return
     * @throws IOException
     */
    public void asyncGetRequest(String url, String currencyCode,
                                DxOkHttpCallback callBack) {
        Request.Builder builder = getDefaultRequestBuild(currencyCode, url);
        Request request = builder.build();
        getOkHttpClient().newCall(request).enqueue(callBack);
    }

    /**
     * 同步的Put请求
     *
     * @param url          请求地址
     * @param parmars      请求参数
     * @param currencyCode 货币种类
     * @return
     * @throws IOException
     */
    public String syncPutRequest(String url, Object parmars, String currencyCode)
            throws IOException, DxException {
        RequestBody body = RequestBody.create(mediaType,
                JsonUtils.getJsonStringByBean(parmars));
        Request.Builder builder = getDefaultRequestBuild(currencyCode, url);
        Request request = builder.put(body).build();
        Response response = getOkHttpClient().newCall(request).execute();
        if (response.isSuccessful()) {
            String result = response.body().string();
            Logger.i("Result", "Put Method: " + result);
            return result;
        } else {
            Logger.i("Result", "Put Method: " + response.toString() + "   ");
            throw new DxException(response.code() + "");
        }
    }


    /**
     * 同步请求
     *
     * @param request Request对象
     * @return
     * @throws IOException
     * @throws DxException
     */
    public String syncRequest(Request request) throws IOException, DxException {
        Response response = getOkHttpClient().newCall(request).execute();
        if (response.isSuccessful()) {
            String result = response.body().string();
            Logger.d("Result", result);
            return result;
        } else {
            Logger.d("Result", response.toString());
            throw new DxException(response.code() + "");
        }
    }

    /**
     * 异步请求
     *
     * @param request  Request对象
     * @param callBack
     * @throws IOException
     */
    public void asyncRequest(Request request, DxOkHttpCallback callBack) {
        // TODO 实现异步的Post请求
        getOkHttpClient().newCall(request).enqueue(callBack);
    }

    /**
     * 获取网络请求头
     *
     * @param currencyCode 货币符号
     * @return
     */
    private Headers getRequestHeaders(String currencyCode) {
        Headers.Builder headerBuilder = new Headers.Builder();
        headerBuilder.add("Authorization", getCredential());
        if (null != currencyCode && !"".equals(currencyCode)) {
            headerBuilder.add("CurrencyCode", currencyCode);
        }
        return headerBuilder.build();
    }

    /**
     * 获取默认的Builder
     *
     * @param currencyCode 货币
     * @return
     */
    private Request.Builder getDefaultRequestBuild(String currencyCode, String url) {
        Request.Builder builder = new Request.Builder();
        builder.headers(getRequestHeaders(currencyCode)).url(url);
        return builder;
    }

}
